#include "../main.h"


struct T {
	JSContext *cx;
	jsval thread_func;
	pthread_t tid;
//	int cx_thread_no;
	int delay;
};

typedef struct {
	JSContext *cx;
	int context_no;
	jsval func;
	pthread_t tid;
	int func_delay;
} CX;


CX *get_context(){
	JSContext *cx;
	pthread_mutex_lock(&mux);
	int i=-1;
	while(lock_cx_thread[++i]);
	++cx_threads_num;
	lock_cx_thread[i]=1;
	cx = cx_thread[i];
	CX *x = calloc(sizeof(CX), 1);
	x->context_no = i;
	x->cx = cx;
	JS_SetContextPrivate(cx, x);
	JS_SetContextThread(cx);
	JS_BeginRequest(cx);
	pthread_mutex_unlock(&mux);
	return x;
}

void release_context(CX *x){
	pthread_mutex_lock(&mux);	
	lock_cx_thread[x->context_no] = 0;
	--cx_threads_num;
	JS_EndRequest(cx);
	JS_ClearContextThread(cx);
	pthread_mutex_unlock(&mux);	
}


void *timeout_proc(void *param){	
	struct timeout *t = (struct timeout *)param;

	CX *x = get_context();
	JSContext *cx = x->cx;
		
	if(t->delay){
		jsrefcount rc = JS_SuspendRequest(cx);
		usleep(1000*t->delay);
		JS_ResumeRequest(cx, rc);
	}
	jsval ret;
	JS_CallFunctionValue(cx, JSVAL_NULL, t->func, 0, JSVAL_NULL, &ret);
	
	release_context(x);
	
	free(t);
	pthread_exit(0);
};


JSBool SetTimeout(JSContext *cx, uintN argc, jsval *vp) {
	jsval func;
	uint32 t;

	if (!JS_ConvertValue(cx, JS_ARGV(cx, vp)[0], JSTYPE_FUNCTION, &func))
		return JS_FALSE;
		
	if(!JS_ConvertArguments(cx, 1, JS_ARGV(cx, vp)+1, "i", &t))
		return JS_FALSE;

	CX *x = get_thread();
	x->func = func;
	x->timeout = t;
	
	pthread_attr_t pattr;
	pthread_attr_init(&pattr);
	pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);
	pthread_create(&x->thread_id, &pattr, thread_proc, t);
	


	if(cx_threads_num>=99){
		trace("Max thread count reached");
		return JS_FALSE;
	}

	struct timeout *t=malloc(sizeof(struct timeout));
	
	
	
	

	return JS_TRUE;
}




JSBool myjs_setTimeout0(JSContext *cx, uintN argc, jsval *vp) {
	if(cx_threads_num>=99){
		trace("Max thread count reached");
		return JS_FALSE;
	}

	struct timeout *t=malloc(sizeof(struct timeout));
	
	if (!(JS_ConvertValue(cx, JS_ARGV(cx, vp)[0], JSTYPE_FUNCTION, &t->func)))
		return JS_FALSE;
	
	if(!JS_ConvertArguments(cx, 1, JS_ARGV(cx, vp)+1, "i", &(t->delay)))
		return JS_FALSE;
	
	
	pthread_attr_t pattr;
	pthread_attr_init(&pattr);
	pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);
	pthread_create(&t->tid, &pattr, timeout_proc, t);

	return JS_TRUE;
}





	int i;
	for (i = 0; i < 100; ++i) {
		cx_thread[i] = JS_NewContext(rt, 8192);
		lock_cx_thread[i] = 0;
	}







